Resizing and Zooming a Window
This programming recipe adds resizing and zooming to your windows by providing a size box and a zoom box.The size box of a Macintosh window is drawn in the content region of the window. When you draw shapes into the window, you don't want to draw them over the size box, so you'd like to be able to set the clip property of the window view port to prevent this. However, QuickDraw GX manages
the clip property of window view ports for you; you don't have control over
this property.To remedy this situation, you create a view port hierarchy. The simple
view port hierarchy in this recipe contains two view ports: a parent view
port and a child view port. You attach the parent view port to your window, but your shape objects reference the child view port. When you draw the shapes, QuickDraw GX still renders them in the window. However, since QuickDraw GX doesn't manage the clip property of the child view port object, you can set this property so that your shapes don't draw over the window's size box.Figure 5-2 shows the simple window hierarchy and the clips of the parent view port and the child view port.
Figure 5-2 A window with a size box and its view hierarchy
The next recipe, "Adding Scrolling to a Window," beginning on page 169, explains how you can use this view port hierarchy to provide scrolling as well.
Overview of Recipe Steps
The steps in this recipe show you how to:
You need to follow the instructions in each step of this recipe to draw QuickDraw GX shapes into windows with a size box.
- Create a Macintosh window with a size box and a zoom box
- Create a parent view port and attach it to the window
- Create a child view port
- Set the clip of the child view port
- Set the child view port to be the default view port
- Respond to window zooming and resizing
Functions Used in This Recipe
QuickDraw GX functions used in this recipe:
GXNewWindowViewPort
"QuickDraw GX and the
Macintosh Environment"
QuickDraw GX Environment and UtilitiesGXGetViewPortViewGroup
"View-Related Objects"
QuickDraw GX ObjectsGXNewViewPort
"View-Related Objects"
QuickDraw GX ObjectsGXSetViewPortParent
"View-Related Objects"
QuickDraw GX ObjectsGXConvertQDPoint
"QuickDraw GX and the
Macintosh Environment"
QuickDraw GX Environment and UtilitiesGXNewRectangle
"Geometric Shapes"
QuickDraw GX GraphicsGXDifferenceShape
"Geometric Operations"
QuickDraw GX GraphicsGXSetViewPortClip
"View-Related Objects"
QuickDraw GX ObjectsGXSetShapeViewPorts
"Transform Objects"
QuickDraw GX ObjectsGXDisposeShape
"Shape Objects"
QuickDraw GX ObjectsStandard Macintosh functions used in this recipe:
NewWindow
"Window Manager"
Macintosh Toolbox EssentialsDrawGrowIcon
"Window Manager"
Macintosh Toolbox EssentialsThis recipe also uses a function from a QuickDraw GX library:
SetDefaultViewPort
graphics library This recipe gives a brief description of these functions; you can find complete reference information for these functions in the Inside Macintosh suite of books.
Recipe Step Descriptions
In this section each step is described individually.
- Create a Macintosh window with a size box and a zoom box
Before you can provide window resizing and zooming, you need to create a window with a size box and a zoom box. You can specify the
zoomDocProc
constant to the standard Macintosh functionNewWindow
to create a window with a zoom box.
gWindow = NewWindow(nil, &windowRect, "\pWindow Title",
true, zoomDocProc, (WindowPtr) -1,
true, 0L);To draw a size box in this window, you use the standard Macintosh function
DrawGrowIcon:
DrawGrowIcon(gWindow);The size box appears in the lower-right corner of the content region of
the window.- Create a parent view port and attach it to the window
Before you can draw QuickDraw GX shapes into the content region of the window, you must create a view port and attach it to the window, as you did in the previous recipe:
gxViewPort gParentViewPort;
gParentViewPort = GXNewWindowViewPort(gWindow);As before, QuickDraw GX manages this view port for you. That is, QuickDraw GX updates the value of this view port's clip and mapping properties to reflect the current size and position of associated window.
Unfortunately, QuickDraw GX does not consider the area covered by the size box when calculating the clip property of the view port. As a result, if you draw shapes directly into this view port, you could possibly draw over the size box.
To solve this problem, in the next step you create a simple view port hierarchy in which the window view port is the parent view port and the view port you draw into is the child view port, whose clip you can alter.
- Create a child view port
To create a view port that is a child of the window view port, you must first determine the view group of the window view port.
Remember that a view group describes an entire viewing coordinate system. As an example, all of your window view ports belong to the onscreen coordinate system.
You can determine which view group a view port belongs to by using the
GXGetViewPortViewGroup
function:
gxViewGroup onscreenViewGroup;
onscreenViewGroup = GXGetViewPortViewGroup(parentViewPort);Since the parent view port belongs to the onscreen drawing environment, this function call finds the onscreen view group.
To create another view port object in the same view group, you would use the
GXNewViewPort
function, which takes the view group as a parameter.
gxViewPort gContentViewPort;
gContentViewPort = GXNewViewPort(onscreenViewGroup);After this function call, the
gContentViewPort
variable references a new view port object in the same view group as the window view port. At this point, however, the two view ports are not connected, other than belonging to the onscreen view group. By specifying the clip and mapping of this new view port incorrectly, you could end up drawing QuickDraw GX shapes anywhere on the screen!You connect the new view port to the window view port by using the
GXSetViewPortParent
function:
GXSetViewPortParent(gContentViewPort, parentViewPort);After this function call, the new view port is a child of the parent view port. Any drawing you do to the child view port is not only clipped by the child view port's clip, but also by the parent view port's clip. Now, if you draw a shape into the child view port, you may draw over the size box, but at least you won't draw outside the window!
- Set the clip of the child view port
To make sure that you don't draw over the window's size box, you
want to specify additional clipping for the child view port. TheMySetContentViewPortClip
function shows how you can set the clip property of the child view port so that you can't draw over the size box.
void MySetContentViewPortClip(WindowPtr theWindow,
gxViewPort theChildViewPort)
{
gxRectangle parentBounds, sizeBoxBounds;
gxShape contentClip, sizeBoxClip;
contentClip = MyGetWindowBoundsShape(gCurrent->window);
GXGetRectangle(contentClip, &parentBounds);
sizeBoxBounds.bottom = parentBounds.bottom;
sizeBoxBounds.right = parentBounds.right;
sizeBoxBounds.top = sizeBoxBounds.bottom
- ff(kScrollBarWidth);
resizeBoxBounds.left = sizeBoxBounds.right
- ff(kScrollBarWidth);
sizeBoxClip = GXNewRectangle(&sizeBoxBounds);
GXDifferenceShape(contentClip, sizeBoxClip);
GXSetViewPortClip(theChildViewPort, contentClip);
GXDisposeShape(contentClip);
GXDisposeShape(sizeBoxClip);
}This function calls the
MyGetWindowBoundsShape
sample function (defined later in this step) to find the bounding rectangle of the window in QuickDraw GX coordinate, translates those into local coordinates (fixed-
point coordinates relative to the origin of the window view port), and encapsulates the bounding rectangle into a rectangle shape. The function then finds the bounding rectangle of the size box.The function then encapsulates the bounding rectangle of the size box into QuickDraw GX rectangle shapes, and uses the
GXDifferenceShape
function to find the shape that describes the area of the content region of the window that is not covered by the size box.The function finally sets the clip of the child view port to be this area. Subsequently, when you draw shapes into the child view port, they'll be clipped so that they don't draw over the size box.
To set the clip of the child view port you created in the previous step, you make this function call:
MySetContentViewPortClip(gWindow, gContentViewPort);The
MyGetWindowBoundsShape
function is defined as follows:
gxShape MyGetWindowBoundsShape(WindowPtr theWindow)
{
Rect theQDRect;
Point QDtopLeft;
Point QDbotRight;
gxPoint GXtopLeft;
gxPoint GXbotRight;
gxRectangle theGXRect;
theRect = theWindow->portRect;
QDtopLeft.h = theRect.left;
QDtopLeft.v = theRect.top;
QDtopLeft.h = theRect.right;
QDtopLeft.v = theRect.bottom;
GXConvertQDPoint(&QDtopLeft, 0, &GXtopLeft);
GXConvertQDPoint(&QDbotRight, 0, &GXbotRight);
theGXRect.top = GXtopLeft.y;
theGXRect.left = GXtopLeft.x;
theGXRect.bottom = GXbotRight.y;
theGXRect.right = GXbotRight.x;
return(GXNewRectangle(&theGXRect));
}- Set the child view port to be the default view port
As in the previous recipe, you can specify each shape that you want to draw into the child view port using the
GXSetShapeViewPorts
function:
GXSetShapeViewPorts(eachShape, 1, &contentViewPort);Alternatively, you can make the child view port be the default view port:
SetDefaultViewPort(contentViewPort);After this function call, shapes you create reference the child view port, which in turn references the parent view port. Therefore, when you draw them, QuickDraw GX renders them into your window, but clips them so that they don't draw over the size box.
- Respond to window zooming and resizing
When the user moves or resizes the window, QuickDraw GX automatically updates the clip and mapping properties of the parent window for you, but it does not update those properties for the child view port.
Fortunately, the origin of the child view port is relative to the origin of its parent, so you don't need to worry about updating the child's mapping. However, you do need to update the clip property of the child view port to reflect the new content region of the window. To do this, you simply call the
MySetContentViewPortClip
function defined in Step 4:
MySetContentViewPortClip(gWindow, gContentViewPort);This function updates the clip property of the child view port to reflect the new window size.
Related Recipes
For other information related to using QuickDraw GX and Macintosh windows, see these recipes:
The recipes in the previous chapter, "Using the QuickDraw GX Environment," show you how to initialize QuickDraw GX and set up the QuickDraw GX debugging facilities. You should read the recipes in that chapter before using any recipes in this chapter.
- "Attaching a View Port to a Macintosh Window," beginning on page 161, shows how to create a Macintosh window and attach a view port object to it. You should be familiar with that recipe before using this one.
- "Adding Scrolling to a Window," described next, shows how to use your view port hierarchy to implement scrolling.
The recipes in Chapter 6, "Handling Graphics," and in Chapter 7, "Handling Typography," show you how to create and manipulate images to draw into
a window.
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help